﻿namespace DotNetUtility.GenericDesignPattern
{
    using System;
    using System.Collections.Generic;

    /// <summary>
    /// To place all the business logic in one place and each of the business logic part defined in the enum. Then using 
    /// StrategyOfTypeSelection object we can easily fetch the related object based on the enum value. So this 
    /// will eliminate lots of nested if - else or switch code block.
    /// </summary>
    /// <typeparam name="TKey">The type of the enum</typeparam>
    /// <typeparam name="TValue">The type of the interface</typeparam>
    /// <example>
    ///     <code>
    ///         class Program
    ///         {
    ///             static void Main(string[] args)
    ///             {
    ///                 StrategyOfTypeSelection<MyEnum,IBusinessRule> strategyOfSelection = new StrategyOfTypeSelection<MyEnum,IBusinessRule>(
    ///                                                     new Dictionary<MyEnum, IBusinessRule>() 
    ///                                                     {
    ///                                                         {MyEnum.One, BusinessRuleImplementionOne},
    ///                                                         {MyEnum.Two, BusinessRuleImplementionTwo}
    ///                                                     }
    ///                                                     );
    ///                 var objectsOne=strategyOfSelection.GetBusinessType(MyEnum.One);
    ///                 var objectTwo=strategyOfSelection.GetBusinessType(MyEnum.Two);
    ///             }
    ///             enum MyEnum
    ///             {
    ///                 One,
    ///                 Two
    ///             }
    ///             public interface IBusinessRule
    ///             {
    ///                 void MethodOne(string item);
    ///             }
    ///             public class BusinessRuleImplementionOne : IBusinessRule
    ///             {
    ///                 public void MethodOne(string item)
    ///                 {
    ///                     Console.WriteLine(item);
    ///                 }
    ///             }
    ///
    ///             public class BusinessRuleImplementionTwo : IBusinessRule
    ///             {
    ///                 public void MethodOne(string item)
    ///                 {
    ///                     Console.WriteLine(item);
    ///                 }
    ///             }
    ///         }    
    ///     </code>
    /// </example>
    /// 

    public class StrategyOfTypeSelection<TKey, TValue>
        where TKey : struct
        where TValue : class
    {
        private Dictionary<TKey, TValue> strategyRepository = new Dictionary<TKey, TValue>();

        /// <summary>
        ///     The constructor to initialize the StrategyOfMethodSelection type and also to initialise the dictionary.
        /// </summary>
        /// <param name="object"></param>
        /// <example>
        ///     <code>
        ///          StrategyOfMethodSelection<MyEnum,IBusinessRule> strategyOfSelection = new StrategyOfMethodSelection<MyEnum,IBusinessRule>(
        ///                             new Dictionary<MyEnum, IBusinessRule>() 
        ///                             {
        ///                                 {MyEnum.One, BusinessRuleImplementionOne},
        ///                                 {MyEnum.Two, BusinessRuleImplementionTwo}
        ///                             }
        ///                             );        
        ///     </code>
        /// </example>
        /// Contributed by Mohammad Rahman
        public StrategyOfTypeSelection(Dictionary<TKey, TValue> @object)
        {
            strategyRepository = @object;
        }

        /// <summary>
        ///    To get the related object based on the given key.
        /// </summary>
        /// <param name="tKey">An enum value which has already a map in the dictionary initialised in the object initialisation time</param>
        /// <returns>related type</returns>
        /// <example>
        ///     <code>
        ///                 strategyOfSelection.GetBusinessType(MyEnum.One)();
        ///     </code>
        /// </example>
        /// Contributed by Mohammad Rahman
        public TValue GetBusinessType(TKey tKey)
        {
            return strategyRepository[tKey];
        }
    }
}
